package m.store.task;

import m.common.action.Action;
import m.common.model.util.ModelUpdate;
import m.common.model.util.QueryCondition;
import m.store.model.*;
import m.store.service.MonthRecordService;
import m.system.RuntimeData;
import m.system.db.TransactionManager;
import m.system.util.DateUtil;
import m.system.util.JSONMessage;
import m.system.util.SystemUtil;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.locks.LockSupport;

public class MonthRecordSupport implements Runnable {
    private MonthRecordSupport(){}
    private static boolean isRun=true;
    static Thread th;
    static final List<Object[]> ls=new ArrayList<>();

    @Override
    public void run() {
        while (true){
            if(ls.isEmpty()){
                TransactionManager.closeConnection();
                LockSupport.park();
                TransactionManager.initConnection();
            }
            if(!isRun) break;
            if(!ls.isEmpty()){
                Object[] arr=ls.remove(0);
                String userOid=(String)arr[0];
                Date date=(Date)arr[1];
                String type=(String)arr[2];
                execute(userOid,date,type);
            }
        }
    }
    private void execute(String userOid,Date date,String type){
        try {
            if(ls.size()<10) Thread.sleep(100L);
            MonthRecord model=RuntimeData.getService(MonthRecordService.class).get(userOid,date,type);
            Date monthStart=DateUtil.getStartMonth(date);
            Date monthEnd=DateUtil.getEndMonth(date);
            switch (type){
                case MonthRecord.Type_Sale:
                    ModelUpdate.init(MonthRecord.class)
                    .set("amount", SaleInfo.class,"ifnull(sum(#{saleAmount}),0)",
                        QueryCondition.and(
                            QueryCondition.ge("saleDate",monthStart),
                            QueryCondition.le("saleDate",monthEnd),
                            QueryCondition.in("type",SaleInfo.Type_Sale),
                            QueryCondition.eq("inputUser.oid",userOid),
                            QueryCondition.eq("status", OrderModel.Status_Done)
                        )
                    )
                    .set("num", SaleInfo.class,"ifnull(sum(1),0)",
                        QueryCondition.and(
                            QueryCondition.ge("saleDate",monthStart),
                            QueryCondition.le("saleDate",monthEnd),
                            QueryCondition.in("type",SaleInfo.Type_Sale),
                            QueryCondition.eq("inputUser.oid",userOid),
                            QueryCondition.eq("status", OrderModel.Status_Done)
                        )
                    )
                    .execute(model.getOid());
                    break;
                case MonthRecord.Type_Stock:
                    ModelUpdate.init(MonthRecord.class)
                    .set("amount", StockInfo.class,"ifnull(sum(#{stockAmount}),0)",
                        QueryCondition.and(
                            QueryCondition.ge("stockDate",monthStart),
                            QueryCondition.le("stockDate",monthEnd),
                            QueryCondition.in("type",StockInfo.Type_Stock),
                            QueryCondition.eq("inputUser.oid",userOid),
                            QueryCondition.eq("status", OrderModel.Status_Done)
                        )
                    )
                    .set("num", StockInfo.class,"ifnull(sum(1),0)",
                        QueryCondition.and(
                            QueryCondition.ge("stockDate",monthStart),
                            QueryCondition.le("stockDate",monthEnd),
                            QueryCondition.in("type",StockInfo.Type_Stock),
                            QueryCondition.eq("inputUser.oid",userOid),
                            QueryCondition.eq("status", OrderModel.Status_Done)
                        )
                    )
                    .execute(model.getOid());
                    break;
                case MonthRecord.Type_Pay:
                    ModelUpdate.init(MonthRecord.class)
                    .set("amount", PayAmount.class,"ifnull(sum(#{payAmount}),0)",
                        QueryCondition.and(
                            QueryCondition.ge("payDate",monthStart),
                            QueryCondition.le("payDate",monthEnd),
                            QueryCondition.eq("inputUser.oid",userOid),
                            QueryCondition.eq("status", OrderModel.Status_Done)
                        )
                    )
                    .set("num", PayAmount.class,"ifnull(sum(1),0)",
                        QueryCondition.and(
                            QueryCondition.ge("payDate",monthStart),
                            QueryCondition.le("payDate",monthEnd),
                            QueryCondition.eq("inputUser.oid",userOid),
                            QueryCondition.eq("status", OrderModel.Status_Done)
                        )
                    )
                    .execute(model.getOid());
                    break;
                case MonthRecord.Type_Income:
                    ModelUpdate.init(MonthRecord.class)
                    .set("amount", IncomeAmount.class,"ifnull(sum(#{incomeAmount}),0)",
                        QueryCondition.and(
                            QueryCondition.ge("incomeDate",monthStart),
                            QueryCondition.le("incomeDate",monthEnd),
                            QueryCondition.eq("inputUser.oid",userOid),
                            QueryCondition.eq("status", OrderModel.Status_Done)
                        )
                    )
                    .set("num", IncomeAmount.class,"ifnull(sum(1),0)",
                        QueryCondition.and(
                            QueryCondition.ge("incomeDate",monthStart),
                            QueryCondition.le("incomeDate",monthEnd),
                            QueryCondition.eq("inputUser.oid",userOid),
                            QueryCondition.eq("status", OrderModel.Status_Done)
                        )
                    )
                    .execute(model.getOid());
                    break;
            }
        } catch (Exception e) {
            Action.directLog("定时任务","更新月度冗余信息失败",this.getClass().getName(),
                    new JSONMessage().push("userOid",userOid).push("date",date).push("type",type).toJSONString(),e);
        }
    }
    /**
     * 添加要更新的商品oid
     */
    public static void add(String userOid, Date date, String type){
        Object[] arr=new Object[]{userOid,date,type};
        if(!ls.contains(arr)) {
            ls.add(arr);
        }
    }

    /**
     * 开始更新
     */
    public static void start(){
        if(null==th){
            th=new Thread(new MonthRecordSupport());
            th.start();
        }else{
            LockSupport.unpark(th);
        }
    }

    public static void close(){
        isRun=false;
        LockSupport.unpark(th);
    }
}
